<!DOCTYPE html>
<html lang="en">
	<head>
		<title>three.js webgl - multiple elements with text</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<style>
			* {
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			body {
				color: #000;
				font-family: Monospace;
				font-size: 13px;

				background-color: #fff;
				margin: auto;
				padding: .5in;
				max-width: 7in;
				text-align: justify;
			}

			.view {
				width: 5in;
				height: 5in;
				margin: auto;
			}

			#c {
				position: fixed;
				left: 0px; top: 0px;
				width: 100%;
				height: 100%;
				background-color: #fff;
				z-index: -1;
			}

			#info {
				position: absolute;
				top: 0px; width: 6.5in;
				padding: 0px;
				text-align: center;
			}

			a {
				color: #0080ff;
			}

			.math {

				text-align: center;

			}

			.math-frac {

				display: inline-block;
				vertical-align: middle;

			}

			.math-num {

				display: block;

			}

			.math-denom {

				display: block;
				border-top: 1px solid;

			}

			.math-sqrt {

				display: inline-block;
				transform: scale(1, 1.3);

			}

			.math-sqrt-stem {

				display: inline-block;
				border-top: 1px solid;
				margin-top: 5px;

			}

		</style>
	</head>
	<body>

		<canvas id="c"></canvas>

		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> - multiple elements with text - webgl</div>

		<script src="../build/three.js"></script>
		<script src="js/controls/OrbitControls.js"></script>

		<script src="js/Detector.js"></script>

		<script>

			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

			var scenes = [], views, t, canvas, renderer;

			window.onload = init;

			function init() {

				var balls = 20;
				var size = .25;

				var colors = [ 'rgb(0,127,255)', 'rgb(255,0,0)', 'rgb(0,255,0)', 'rgb(0,255,255)',
        				       'rgb(255,0,255)', 'rgb(255,0,127)', 'rgb(255,255,0)', 'rgb(0,255,127)' ];

				canvas = document.getElementById( 'c' );

				renderer = new THREE.WebGLRenderer( { canvas: canvas, antialias: true } );
				renderer.setClearColor( 0xffffff, 1 );
				renderer.setPixelRatio( window.devicePixelRatio );

				views = document.querySelectorAll( '.view' );

				for ( var n = 0 ; n < views.length ; n++ ) {

					var scene = new THREE.Scene();

					var geometry = new THREE.Geometry();
					var geometry0 = new THREE.Geometry();

					if ( views[n].lattice ) {

						var range = balls / 2;
						for ( var i = -range ; i <= range ; i++ ) {

							for ( var j = -range ; j <= range ; j++ ) {

								for ( var k = -range ; k <= range ; k++ ) {

									geometry.vertices.push( new THREE.Vector3( i, j, k ) );
									geometry0.vertices.push( new THREE.Vector3( i, j, k ) );

								}

							}

						}

					} else {

						for ( var m = 0 ; m < Math.pow( balls, 3 ) ; m++ ) {

							var i = balls * Math.random() - balls / 2;
							var j = balls * Math.random() - balls / 2;
							var k = balls * Math.random() - balls / 2;

							geometry.vertices.push( new THREE.Vector3( i, j, k ) );
							geometry0.vertices.push( new THREE.Vector3( i, j, k ) );

						}

					}

					var index = Math.floor( colors.length * Math.random() );

					var canvas2 = document.createElement( 'canvas' );
					canvas2.width = 128;
					canvas2.height = 128;
					var context = canvas2.getContext( '2d' );
					context.arc( 64, 64, 64, 0, 2 * Math.PI );
					context.fillStyle = colors[ index ];
					context.fill();
					var texture = new THREE.Texture( canvas2 );
					texture.needsUpdate = true;

					var material = new THREE.PointsMaterial( { size: size, map: texture, transparent: true, alphaTest: .1 } );

					scene.add( new THREE.Points( geometry, material ) );

					scene.userData.view = views[n];
					scene.userData.geometry0 = geometry0;

					var camera = new THREE.PerspectiveCamera( 75, 1, .1, 100 );
					camera.position.set( 0, 0, 1.2*balls );
					scene.userData.camera = camera;

					var controls = new THREE.OrbitControls( camera, views[n] );
					scene.userData.controls = controls;

					scenes.push( scene );

				}

				t = 0;
				animate();

			}

			function updateSize() {

				var width = canvas.clientWidth;
				var height = canvas.clientHeight;

				if ( canvas.width !== width || canvas.height != height ) {

					renderer.setSize( width, height, false );

				}

			}

			function animate() {

				render();
				requestAnimationFrame( animate );

			}

			function render() {

				updateSize();

				renderer.setClearColor( 0xffffff );
				renderer.setScissorTest( false );
				renderer.clear();

				renderer.setClearColor( 0x000000 );
				renderer.setScissorTest( true );

				scenes.forEach( function( scene ) {

					var rect = scene.userData.view.getBoundingClientRect();
					// check if it's offscreen. If so skip it
					if ( rect.bottom < 0 || rect.top  > renderer.domElement.clientHeight ||
						 rect.right  < 0 || rect.left > renderer.domElement.clientWidth ) {
						return;  // it's off screen
					}
					// set the viewport
					var width  = rect.right - rect.left;
					var height = rect.bottom - rect.top;
					var left   = rect.left;
					var bottom = renderer.domElement.clientHeight - rect.bottom;
					renderer.setViewport( left, bottom, width, height );
					renderer.setScissor( left, bottom, width, height );

					renderer.render( scene, scene.userData.camera );

					for ( var i = 0 ; i < scene.children[0].geometry.vertices.length ; i++ ) {

						var v0 = scene.userData.geometry0.vertices[i];
						var v = scene.userData.view.displacement( v0.x, v0.y, v0.z, t/5 );
						scene.children[0].geometry.vertices[i].set( v.x + v0.x, v.y + v0.y, v.z + v0.z );

					}

					scene.children[0].geometry.verticesNeedUpdate = true;

				} );

				t ++;

			}

		</script>

		<p>Sound waves whose geometry is determined by a single dimension, plane waves, obey the wave equation</p>

		<!-- css math formatting inspired by http://mathquill.com/mathquill/mathquill.css -->

		<div class="math">

			<span class="math-frac">
				<span class="math-num">
					&part;<sup>2</sup><i>u</i>
				</span>
				<span class="math-denom">
					&part;<i>r</i><sup>2</sup>
				</span>
			</span>

			&minus;

			<span class="math-frac">
				<span class="math-num">
					1<sup></sup> <!-- sup for vertical alignment -->
				</span>
				<span class="math-denom">
					<i>c</i><sup>2</sup>
				</span>
			</span>

			<span class="math-frac">
				<span class="math-num">
					&part;<sup>2</sup><i>u</i>
				</span>
				<span class="math-denom">
					&part;<i>t</i><sup>2</sup>
				</span>
			</span>

			=&nbsp;0

		</div>

		<p>where <i>c</i> designates the speed of sound in the medium. The monochromatic solution for plane waves will be taken to be</p>

		<div class="math">

			<i>u</i>(<i>r</i>,<i>t</i>)&thinsp;=&nbsp;sin(<i>k</i><i>r</i>&thinsp;&plusmn;&thinsp;&omega;<i>t</i>)

		</div>

		<p>where &omega; is the frequency and <i>k</i>=&omega;/<i>c</i> is the wave number. The sign chosen in the argument determines the direction of movement of the waves.</p>

		<p>Here is a plane wave moving on a three-dimensional lattice of atoms:</p>

		<div class="view">

		<script>

			var parent = document.scripts[ document.scripts.length - 1 ].parentNode;

			parent.displacement = function( x, y, z, t ) {

				return new THREE.Vector3( Math.sin( x - t ), 0, 0);

			};

			parent.lattice = true;

		</script>

		</div>

		<p>Here is a plane wave moving through a three-dimensional random distribution of molecules:</p>

		<div class="view">

		<script>

			var parent = document.scripts[ document.scripts.length - 1 ].parentNode;

			parent.displacement = function( x, y, z, t ) {

				return new THREE.Vector3( Math.sin( x - t ), 0, 0);

			};

			parent.lattice = false;

		</script>

		</div>

		<p>Sound waves whose geometry is determined by two dimensions, cylindrical waves, obey the wave equation</p>

		<div class="math">

			<span class="math-frac">
				<span class="math-num">
					&part;<sup>2</sup><i>u</i>
				</span>
				<span class="math-denom">
					&part;<i>r</i><sup>2</sup>
				</span>
			</span>

			&plus;

			<span class="math-frac">
				<span class="math-num">
					1
				</span>
				<span class="math-denom">
					<i>r</i>
				</span>
			</span>

			<span class="math-frac">
				<span class="math-num">
					&part;<i>u</i>
				</span>
				<span class="math-denom">
					&part;<i>r</i>
				</span>
			</span>

			&minus;

			<span class="math-frac">
				<span class="math-num">
					1<sup></sup> <!-- sup for vertical alignment -->
				</span>
				<span class="math-denom">
					<i>c</i><sup>2</sup>
				</span>
			</span>

			<span class="math-frac">
				<span class="math-num">
					&part;<sup>2</sup><i>u</i>
				</span>
				<span class="math-denom">
					&part;<i>t</i><sup>2</sup>
				</span>
			</span>

			=&nbsp;0

		</div>

		<p>The monochromatic solution for cylindrical sound waves will be taken to be</p>

		<div class="math">

			<i>u</i>(<i>r</i>,<i>t</i>)&thinsp;=

			<span class="math-frac">
				<span class="math-num">
					sin(<i>k</i><i>r</i>&thinsp;&plusmn;&thinsp;&omega;<i>t</i>)
				</span>
				<span class="math-denom">
					<span class="math-sqrt">&radic;</span><span class="math-sqrt-stem"><i>r</i></span>
				</span>
			</span>

		</div>

		<p>Here is a cylindrical wave moving on a three-dimensional lattice of atoms:</p>

		<div class="view">

		<script>

			var parent = document.scripts[ document.scripts.length - 1 ].parentNode;

			parent.displacement = function( x, y, z, t ) {

				if ( x * x + y * y < 0.01 ) {

					return new THREE.Vector3( 0, 0, 0);

				} else {

					var rho = Math.sqrt( x * x + y * y );
					var phi = Math.atan2( y, x );

					return new THREE.Vector3( 1.5 * Math.cos( phi ) * Math.sin( rho - t ) / Math.sqrt( rho ), 1.5 * Math.sin( phi ) * Math.sin( rho - t ) / Math.sqrt( rho ), 0);

				}

			};

			parent.lattice = true;

		</script>

		</div>

		<p>Here is a cylindrical wave moving through a three-dimensional random distribution of molecules:</p>

		<div class="view">

		<script>

			var parent = document.scripts[ document.scripts.length - 1 ].parentNode;

			parent.displacement = function( x, y, z, t ) {

				if ( x * x + y * y < 0.01 ) {

					return new THREE.Vector3( 0, 0, 0);

				} else {

					var rho = Math.sqrt( x * x + y * y );
					var phi = Math.atan2( y, x );

					return new THREE.Vector3( 1.5 * Math.cos( phi ) * Math.sin( rho - t ) / Math.sqrt( rho ), 1.5 * Math.sin( phi ) * Math.sin( rho - t ) / Math.sqrt( rho ), 0);

				}

			};

			parent.lattice = false;

		</script>

		</div>

		<p>Sound waves whose geometry is determined by three dimensions, spherical waves, obey the wave equation</p>

		<div class="math">

			<span class="math-frac">
				<span class="math-num">
					&part;<sup>2</sup><i>u</i>
				</span>
				<span class="math-denom">
					&part;<i>r</i><sup>2</sup>
				</span>
			</span>

			&plus;

			<span class="math-frac">
				<span class="math-num">
					2
				</span>
				<span class="math-denom">
					<i>r</i>
				</span>
			</span>

			<span class="math-frac">
				<span class="math-num">
					&part;<i>u</i>
				</span>
				<span class="math-denom">
					&part;<i>r</i>
				</span>
			</span>

			&minus;

			<span class="math-frac">
				<span class="math-num">
					1<sup></sup> <!-- sup for vertical alignment -->
				</span>
				<span class="math-denom">
					<i>c</i><sup>2</sup>
				</span>
			</span>

			<span class="math-frac">
				<span class="math-num">
					&part;<sup>2</sup><i>u</i>
				</span>
				<span class="math-denom">
					&part;<i>t</i><sup>2</sup>
				</span>
			</span>

			=&nbsp;0

		</div>

		<p>The monochromatic solution for spherical sound waves will be taken to be</p>

		<div class="math">

			<i>u</i>(<i>r</i>,<i>t</i>)&thinsp;=

			<span class="math-frac">
				<span class="math-num">
					sin(<i>k</i><i>r</i>&thinsp;&plusmn;&thinsp;&omega;<i>t</i>)
				</span>
				<span class="math-denom">
					<i>r</i>
				</span>
			</span>

		</div>

		<p>Here is a spherical wave moving on a three-dimensional lattice of atoms:</p>

		<div class="view">

		<script>

			var parent = document.scripts[ document.scripts.length - 1 ].parentNode;

			parent.displacement = function( x, y, z, t ) {

				if ( x * x + y * y + z * z < 0.01 ) {

					return new THREE.Vector3( 0, 0, 0);

				} else {

					var r = Math.sqrt( x * x + y * y + z * z );
					var theta = Math.acos( z / r );
					var phi = Math.atan2( y, x );

					return new THREE.Vector3( 3 * Math.cos( phi ) * Math.sin( theta ) * Math.sin( r - t ) / r , 3 * Math.sin( phi ) * Math.sin( theta ) * Math.sin( r - t ) / r , 3 * Math.cos( theta ) * Math.sin( r - t ) / r );

				}

			};

			parent.lattice = true;

		</script>

		</div>

		<p>Here is a spherical wave moving through a three-dimensional random distribution of molecules:</p>

		<div class="view">

		<script>

			var parent = document.scripts[ document.scripts.length - 1 ].parentNode;

			parent.displacement = function( x, y, z, t ) {

				if ( x * x + y * y + z * z < 0.01 ) {

					return new THREE.Vector3( 0, 0, 0);

				} else {

					var r = Math.sqrt( x * x + y * y + z * z );
					var theta = Math.acos( z / r );
					var phi = Math.atan2( y, x );

					return new THREE.Vector3( 3 * Math.cos( phi ) * Math.sin( theta ) * Math.sin( r - t ) / r , 3 * Math.sin( phi ) * Math.sin( theta ) * Math.sin( r - t ) / r , 3 * Math.cos( theta ) * Math.sin( r - t ) / r );

				}
			};

			parent.lattice = false;

		</script>

		</div>

		<p>The mathematical description of sound waves can be carried to higher dimensions, but one needs to wait for Four.js and its higher-dimensional successors to attempt visualizations.</p>

	</body>
</html>
